from fastapi import FastAPI, Depends, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session
from typing import List, Dict, Any, Optional
import uvicorn
import threading
import time

from src.models.database.database import get_db
from src.services.plate_service import PlateService, PlateCreate, PlateUpdate, PlateResponse
from src.services.sample_service import SampleService, SamplePlaceRequest, SampleLocationResponse
from src.core.config import config

# 创建FastAPI应用
app = FastAPI(
    title="WMS Sample API",
    description="料位管理系统API",
    version="1.0.0"
)

# 添加CORS中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=config.cors_origins,  # 从配置文件读取允许的源
    allow_credentials=True,
    allow_methods=["*"],  # 允许所有HTTP方法
    allow_headers=["*"],  # 允许所有请求头
)

# 全局变量存储服务器实例
server_thread = None
server_instance = None

@app.get("/", summary="根路径")
async def root():
    return {"message": "WMS Sample API 服务运行中", "version": "1.0.0"}

@app.get("/api/health", summary="健康检查")
async def health_check():
    return {"status": "healthy", "timestamp": time.time()}

# ==================== 料盘管理接口 ====================

@app.get("/api/plates", response_model=List[PlateResponse], summary="获取所有料盘")
async def get_plates(db: Session = Depends(get_db)):
    """获取所有料盘信息"""
    try:
        service = PlateService(db)
        return service.get_all_plates()
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/api/plates", summary="创建料盘")
async def create_plate(plate_data: PlateCreate, db: Session = Depends(get_db)):
    """创建新料盘"""
    try:
        service = PlateService(db)
        plate = service.create_plate(plate_data)
        return {"success": True, "message": f"料盘 '{plate.name}' 创建成功", "plate_id": plate.id}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.put("/api/plates/{plate_name}", summary="更新料盘")
async def update_plate(plate_name: str, plate_data: PlateUpdate, db: Session = Depends(get_db)):
    """更新料盘信息"""
    try:
        service = PlateService(db)
        plate = service.update_plate(plate_name, plate_data)
        if not plate:
            raise HTTPException(status_code=404, detail=f"料盘 '{plate_name}' 不存在")
        return {"success": True, "message": f"料盘 '{plate_name}' 更新成功"}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.put("/api/plates/{plate_name}/reset", summary="重置料盘")
async def reset_plate(plate_name: str, plate_data: PlateUpdate, db: Session = Depends(get_db)):
    """重置料盘（清空所有料位后更新容量）"""
    try:
        service = PlateService(db)
        plate = service.update_plate_with_reset(plate_name, plate_data)
        if not plate:
            raise HTTPException(status_code=404, detail=f"料盘 '{plate_name}' 不存在")
        return {"success": True, "message": f"料盘 '{plate_name}' 已重置并更新成功"}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.put("/api/plates/{plate_name}/clear", summary="批量清空料位")
async def clear_plate_positions(
    plate_name: str, 
    task_id: Optional[str] = Query("", description="任务ID"),
    operator: Optional[str] = Query("system", description="操作员"),
    db: Session = Depends(get_db)
):
    """批量清空料盘的所有料位（保留禁用状态）"""
    try:
        service = PlateService(db)
        success = service.clear_all_positions(plate_name, task_id, operator)
        if not success:
            raise HTTPException(status_code=404, detail=f"料盘 '{plate_name}' 不存在")
        return {"success": True, "message": f"料盘 '{plate_name}' 的所有样品已清空", "task_id": task_id, "operator": operator}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.delete("/api/plates/{plate_name}", summary="删除料盘")
async def delete_plate(plate_name: str, db: Session = Depends(get_db)):
    """删除料盘"""
    try:
        service = PlateService(db)
        success = service.delete_plate(plate_name)
        if not success:
            raise HTTPException(status_code=404, detail=f"料盘 '{plate_name}' 不存在")
        return {"success": True, "message": f"料盘 '{plate_name}' 删除成功"}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/api/plates/{plate_name}/positions", summary="获取料盘料位")
async def get_plate_positions(plate_name: str, db: Session = Depends(get_db)):
    """获取指定料盘的所有料位信息"""
    try:
        service = PlateService(db)
        positions = service.get_plate_positions(plate_name)
        if not positions:
            raise HTTPException(status_code=404, detail=f"料盘 '{plate_name}' 不存在")
        return {"plate_name": plate_name, "positions": positions}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/api/plates/{plate_name}/available", summary="获取可用料位")
async def get_available_positions(plate_name: str, db: Session = Depends(get_db)):
    """获取指定料盘的可用料位索引列表"""
    try:
        service = PlateService(db)
        available_positions = service.get_available_positions(plate_name)
        return {
            "plate_name": plate_name, 
            "available_positions": available_positions,
            "count": len(available_positions)
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# ==================== 样品管理接口 ====================

@app.post("/api/samples/place", summary="放置样品")
async def place_sample(request: SamplePlaceRequest, db: Session = Depends(get_db)):
    """放置样品到指定料位"""
    try:
        service = SampleService(db)
        result = service.place_sample(request)
        return result
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.delete("/api/samples/{plate_name}/{sample_id}", summary="移除样品")
async def remove_sample(
    plate_name: str,
    sample_id: str, 
    task_id: Optional[str] = Query("", description="任务ID"),
    operator: Optional[str] = Query("system", description="操作员"),
    db: Session = Depends(get_db)
):
    """移除指定料盘中的样品"""
    try:
        service = SampleService(db)
        result = service.remove_sample(plate_name, sample_id, task_id, operator)
        return result
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/api/samples/{sample_id}/location", response_model=SampleLocationResponse, summary="查询样品位置")
async def get_sample_location(sample_id: str, db: Session = Depends(get_db)):
    """查询样品位置"""
    try:
        service = SampleService(db)
        location = service.find_sample_location(sample_id)
        if not location:
            raise HTTPException(status_code=404, detail=f"样品 '{sample_id}' 不存在")
        return location
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/api/samples/{plate_name}/{sample_id}/location", response_model=SampleLocationResponse, summary="根据料盘名和样品ID查询位置")
async def get_sample_location_in_plate(plate_name: str, sample_id: str, db: Session = Depends(get_db)):
    """根据料盘名和样品ID查询样品位置"""
    try:
        service = SampleService(db)
        location = service.find_sample_location_in_plate(plate_name, sample_id)
        if not location:
            raise HTTPException(status_code=404, detail=f"样品 '{sample_id}' 在料盘 '{plate_name}' 中不存在")
        return location
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/api/plates/{plate_name}/first-available", summary="获取第一个可用料位")
async def get_first_available_position(plate_name: str, db: Session = Depends(get_db)):
    """获取指定料盘的第一个可用料位索引"""
    try:
        service = SampleService(db)
        position_index = service.get_first_available_position(plate_name)
        if position_index is None:
            return {"plate_name": plate_name, "available_position": None, "message": "无可用料位"}
        return {"plate_name": plate_name, "available_position": position_index}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# ==================== 任务追踪接口 ====================

@app.get("/api/tasks/{task_id}/positions", summary="根据任务ID查询料位")
async def get_positions_by_task(task_id: str, db: Session = Depends(get_db)):
    """根据任务ID查询相关的所有料位操作"""
    try:
        service = SampleService(db)
        positions = service.get_positions_by_task(task_id)
        return {
            "task_id": task_id,
            "positions": positions,
            "count": len(positions)
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# ==================== 料位控制接口 ====================

@app.post("/api/positions/disable/{plate_name}/{position_index}", summary="禁用料位")
async def disable_position(
    plate_name: str, 
    position_index: int,
    task_id: Optional[str] = Query("", description="任务ID"),
    operator: Optional[str] = Query("system", description="操作员"),
    db: Session = Depends(get_db)
):
    """禁用指定料位"""
    try:
        service = SampleService(db)
        result = service.disable_position(plate_name, position_index, task_id, operator)
        return result
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/api/positions/enable/{plate_name}/{position_index}", summary="启用料位")
async def enable_position(
    plate_name: str, 
    position_index: int,
    task_id: Optional[str] = Query("", description="任务ID"),
    operator: Optional[str] = Query("system", description="操作员"),
    db: Session = Depends(get_db)
):
    """启用指定料位"""
    try:
        service = SampleService(db)
        result = service.enable_position(plate_name, position_index, task_id, operator)
        return result
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# ==================== 服务器控制函数 ====================

def start_server(host: str = None, port: int = None):
    """启动API服务器"""
    global server_thread, server_instance
    
    if server_thread and server_thread.is_alive():
        return False, "服务器已在运行中"
    
    host = host or config.api_host
    port = port or config.api_port
    
    def run_server():
        try:
            print(f"正在启动API服务器: {host}:{port}")
            uvicorn.run(
                app,
                host=host,
                port=port,
                log_level="info",
                access_log=False  # 减少日志输出
            )
        except Exception as e:
            print(f"API服务器启动失败: {e}")
    
    server_thread = threading.Thread(target=run_server, daemon=True)
    server_thread.start()
    
    # 等待服务器启动
    time.sleep(3)
    
    return True, f"API服务器已启动: http://{host}:{port}"

def stop_server():
    """停止API服务器"""
    global server_thread, server_instance
    
    if not server_thread or not server_thread.is_alive():
        return False, "服务器未运行"
    
    if server_instance:
        server_instance.should_exit = True
    
    return True, "API服务器已停止"

def is_server_running():
    """检查服务器是否运行中"""
    global server_thread
    return server_thread and server_thread.is_alive()

if __name__ == "__main__":
    # 直接运行时启动服务器
    uvicorn.run(app, host=config.api_host, port=config.api_port) 